#include <iostream>
#include <vector>
#include <sstream>
#include <fstream>

#include "CLineTokenizer.h"

using namespace std;

void print_out(CBlockStream *block_stream, vector<int> &ppos, int kpos, char delim, char eol, long limit)
{
	int key = kpos-1;
	vector< vector<string> > kv_vectors;
	while(block_stream->getline(kv_vectors, delim, limit)!=0) {
		if(ppos.size()>0) {
			for(int i=0;i<kv_vectors.size();i++) {
				if(kv_vectors[i].size()<=key) continue;

				cout << "#[" << kv_vectors[i][key] << "]" << endl;

				for(int j=0;j<ppos.size();j++) {
					cout << kv_vectors[i][ppos[j]-1] << delim;
				}
				cout << endl;
			}
		}
		else {
			for(int i=0;i<kv_vectors.size();i++) {
				if(kv_vectors[i].size()<=key) continue;

				cout << "#[" << kv_vectors[i][key] << "]" << endl;

				for(int j=0;j<kv_vectors[i].size();j++) {
					cout << kv_vectors[i][j] << delim;
				}
				cout << endl;
			}
		}

		kv_vectors.clear();
	}
}

int main(int argc,char *argv[])
{
	if(argc<2) {
		cout << "Usages : " << argv[0] << " -f <file> -k <pos> -d <delim> -e <eol> -p <pos to print> -b <block> -t <blocks> -123" << endl;
		cout << "\t\t-1 : use just CBlockStream's getline()" << endl;
/*
		cout << "\t\t-2 : use threads" << endl;
*/
		cout << "\t\t-3 : not use thread, but just getToken() method" << endl;
		exit(-1);
	}

	int opt;
	static char optstr[] = "fkpdebt123";

	char *file = NULL;
	int kpos = 1;
	vector<int> ppos;
	char delim = '\t';
	char eol = '\n';
	long limit = MAX_LINE_LIMIT;
	int block = 0;
	int blocks = 1;
	int mode = 1;

	while((opt=getopt(argc,argv,optstr))!=-1) {
		switch(opt) {
			case 'f' :
				file = argv[optind++];
				break;
			case 'k' :
				kpos = atoi(argv[optind++]);
				break;
			case 'p' :
				ppos.push_back(atoi(argv[optind++]));
				break;
			case 'd' :
				if(strcmp(argv[optind],"\\t")==0) delim = '\t';
				else if(strcmp(argv[optind],"\\n")==0) delim = '\n';
				else delim = (char) *(argv[optind++]);
				break;
			case 'e' :
				if(strcmp(argv[optind],"\\t")==0) eol  = '\t';
				else if(strcmp(argv[optind],"\\n")==0) eol = '\n';
				else eol = (char) *(argv[optind++]);
				break;
			case 'b' :
				block = atoi(argv[optind++]);
				break;
			case 't' :
				blocks = atoi(argv[optind++]);
				break;
			case '1' :
				mode = 1;
				break;
			case '2' :
				mode = 2;
				break;
			case '3' :
				mode = 3;
				break;
		}
	}

	if(file!=NULL) {
		// just function tokenizer with getline()
		if(mode==1) {
			CBlockStream block_stream(file);

			block_stream.resize(50);
			block_stream.assignBlock(block,blocks);
			print_out(&block_stream, ppos, kpos, delim, eol, limit);
		}
/*
		// tokenizer with thread
		else if(mode==2) {
			vector< CLineTokenizer *> tok_threads;

			for(int i=0;i<blocks;i++) {
				CLineTokenizer *thr = new CLineTokenizer();
				
				tok_threads.push_back(thr);

				tok_threads[i]->input(file);
				tok_threads[i]->format(kpos, ppos);
				tok_threads[i]->filter(delim, eol, limit);
				tok_threads[i]->assign(i, blocks);
				tok_threads[i]->start();
			}

			for(int i=0;i<blocks;i++) {
				tok_threads[i]->join();
				delete tok_threads[i];
			}
		}
*/
		// tokenizer without thread
		else if(mode==3) {
			CLineTokenizer *line_tokenizer = new CLineTokenizer();
			line_tokenizer->input(file);
			//line_tokenizer->format(kpos, ppos);
			line_tokenizer->format(kpos);
			line_tokenizer->filter(delim, eol, limit);
			//line_tokenizer->assign(block, blocks);
			

			vector< vector<string> > token;
			while(line_tokenizer->getToken(token)>0) {
				int key = kpos-1;
				for(int i=0;i<token.size();i++) {
					// print key
					//cout << "[" << token[i][key] << "]";

					for(int j=0;j<token[i].size();j++) {
						cout << token[i][j] << delim;
					}
					cout << endl;
				}

				token.clear();
			}

			
			delete line_tokenizer; 
		}
	}
	else {
		CLineTokenizer *line_tokenizer = new CLineTokenizer();

		line_tokenizer->input(cin.rdbuf());
/*
stringstream ss;
for(int i=0;i<100;i++) {
	ss << i << "\t" << "woorung nara" << endl;
}
line_tokenizer->input(ss.rdbuf());
*/

		line_tokenizer->format(kpos);
		line_tokenizer->filter(delim, eol, limit);

		vector< vector<string> > token;
		while(line_tokenizer->getToken(token)>0) {
			int key = kpos-1;
			for(int i=0;i<token.size();i++) {
				// print key
				cout << "[" << token[i][key] << "]";

				for(int j=0;j<token[i].size();j++) {
					cout << token[i][j] << delim;
				}
				cout << endl;
			}

			token.clear();
		}

		delete line_tokenizer; 
	}
}
